/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thesis.utils;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Hashtable;
import java.util.LinkedList;

import com.thesis.algorithm.Device;
import com.thesis.algorithm.Sample;
import com.thesis.algorithm.Sequence;
import com.thesis.algorithm.SequenceElement;
import com.thesis.downloader.downloaderBusRoute;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * @author Aya Hikaru
 */
public class BusControl {

    // temporary do not use reversedistance
    // static public final double ReverseDistance = 0.4; //400m
	static private final double AcceptRadiusForFirstAndLast = .10; // 200m
    static private final double AcceptRadius = .05; // 100m
    static private final String allBusStopBinary = "bus\\allBusStop.bin";
    static private final String allBusRouteBinary = "bus\\allBusRoute.bin";
    static private final String allBusStopText = "bus\\allBusStop.txt";
    static private final String allBusRouteText = "bus\\allBusRoute.txt";
    private Hashtable<Character, BusStop> allBusStop = new Hashtable<Character, BusStop>();
    private Hashtable<Short, BusRoute> allBusRoute = new Hashtable<Short, BusRoute>();
    public Hashtable<Short, Hashtable<Character, Hashtable <Character, Double>>> distanceBusStops = new Hashtable<Short, Hashtable<Character, Hashtable<Character, Double>>>();
    static public double DistanceDiffToSave = .5;
    public BusControl() {
        readFromTextFile();
    }

    public void countBusStops() {
        LinkedList<Character> tmp = new LinkedList<Character>();
        BusRoute br = null;
        BusStop bs = null;
        for (short busRouteID : CONSTANTS.BUS_COLLECTED_ROUTE) {
            br = allBusRoute.get(busRouteID);
            for (char c : br.BusStopIDList) {
                if (tmp.contains(c)) {
                } else {
                    tmp.add(c);
                }
            }
        }
        Set<Character> keys = allBusStop.keySet();
        int countInTownCollected = 0;
        int countInTown = 0;
        for (char c : keys) {
            bs = allBusStop.get(c);
            if (!bs.mDistrict.contains("0") && !bs.mDistrict.contains("1") && !bs.mDistrict.contains("2") && !bs.mDistrict.contains("3")
                    && !bs.mDistrict.contains("4") && !bs.mDistrict.contains("5") && !bs.mDistrict.contains("6") && !bs.mDistrict.contains("7")
                    && !bs.mDistrict.contains("8") && !bs.mDistrict.contains("9")) {
            } else {
                if (tmp.contains(c)) {
                    countInTownCollected++;
                }
                countInTown++;
            }
        }
        System.out.println("WE HAVE " + tmp.size() + " OF " + keys.size());
        System.out.println("WE HAVE INTOWN " + countInTownCollected + " OF " + countInTown);
    }

    public String returnMarkerString() {
        String result = "";
        LinkedList<Character> tmp = new LinkedList<Character>();
        BusRoute br = null;
        BusStop bs = null;
        for (short busRouteID : CONSTANTS.BUS_COLLECTED_ROUTE) {
            br = allBusRoute.get(busRouteID);
            for (char c : br.BusStopIDList) {
                if (tmp.contains(c)) {
                } else {
                    tmp.add(c);
                }
            }
        }
        Set<Character> keys = allBusStop.keySet();
        for (char c : keys) {
            bs = allBusStop.get(c);

            if (tmp.contains(c)) {
            } else {
                if (!bs.mDistrict.contains("0") && !bs.mDistrict.contains("1") && !bs.mDistrict.contains("2") && !bs.mDistrict.contains("3")
                        && !bs.mDistrict.contains("4") && !bs.mDistrict.contains("5") && !bs.mDistrict.contains("6") && !bs.mDistrict.contains("7")
                        && !bs.mDistrict.contains("8") && !bs.mDistrict.contains("9")) {
                } else {
                    result += "new google.maps.Marker({"
                            + "position: new google.maps.LatLng(" + bs.mLat + "," + bs.mLng + "),"
                            + "map: map,"
                            + "icon: {path: google.maps.SymbolPath.CIRCLE, scale: 3}});\n";
                }
            }
        }
        for (char c : tmp) {
            bs = allBusStop.get(c);
            result += "new google.maps.Marker({"
                    + "position: new google.maps.LatLng(" + bs.mLat + "," + bs.mLng + "),"
                    + "map: map});\n";
        }
        return result;
    }

    public void countDistanceBasedonBusStops() {
        double prevLat = 0;
        double prevLng = 0;
        double distance = 0;
        double sum = 0;
        BusRoute br = null;
        BusStop bs = null;
        boolean first = true;
        for (short busRouteID : CONSTANTS.BUS_COLLECTED_ROUTE) {
            distance = 0;
            br = allBusRoute.get(busRouteID);
            for (char c : br.BusStopIDList) {
                bs = allBusStop.get(c);
                if (first == true) {
                    prevLat = bs.mLat;
                    prevLng = bs.mLng;
                    first = false;
                } else {
                    distance += CoordinateConversion.LatLngDistance(bs.mLat, bs.mLng, prevLat, prevLng);
                    prevLat = bs.mLat;
                    prevLng = bs.mLng;
                }
            }
            System.out.println("BUS ROUTE: " + busRouteID + " Distance: " + distance);
            sum += distance;
        }
        System.out.println("SUM: " + sum);

    }

    private void readFromBinaryFile() {
        // READ BUSSTOP
        try {
            BusStop temp;
            DataInputStream in = new DataInputStream(new FileInputStream(
                    allBusStopBinary));
            while (true) {
                try {
                    temp = new BusStop();
                    temp.mStreetNo = in.readUTF();// in.readChar();
                    temp.mStreetName = in.readUTF();// in.readChar();
                    temp.mDistrict = in.readUTF();// in.readChar();
                    temp.mID = in.readChar();// in.readChar();
                    temp.mLat = in.readDouble();// in.readChar();
                    temp.mLng = in.readDouble();// in.readChar();
                    if (!allBusStop.containsKey(temp.mID)) {
                        allBusStop.put(temp.mID, temp);
                    }
                } catch (Exception e) {
                    break;
                }
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        // READ BUS ROUTE
        try {
            downloaderBusRoute temp = new downloaderBusRoute(0, true);
            DataInputStream in = new DataInputStream(new FileInputStream(
                    allBusRouteBinary));
            char a;
            BusRoute route;

            while (true) {
                try {
                    route = new BusRoute();

                    route.BusRouteID = in.readShort();
                    // System.out.print(route.BusRouteID + "==");
                    while ((a = (char) in.readChar()) != 10) // \n charater
                    {
                        route.BusStopIDList.add(a);
                        // System.out.print(a + " ");
                    }
                    if (!allBusRoute.containsKey(route.BusRouteID)) {
                        allBusRoute.put(route.BusRouteID, route);
                    }
                } catch (Exception e) {
                    break;
                }
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    public static String readLine(InputStream in) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        while (true) {
            int b = in.read();
            if (b < 0) {
                throw new IOException("Data truncated");
            }
            if (b == 0x0A) {
                break;
            }
            buffer.write(b);
        }
        return new String(buffer.toByteArray(), "UTF-8");
    }

    // TODO: fix binary files
    // TODO: fix readtext busroute
    private void readFromTextFile() {
        // READ BUSSTOP
        try {
            BusStop temp;
            DataInputStream in = new DataInputStream(new FileInputStream(
                    allBusStopText));
            String str;
            while (true) {
                try {
                    str = readLine(in);
                    temp = new BusStop(str);
                    // System.out.println(temp.getAddress());
                    if (!allBusStop.containsKey(temp.mID)) {
                        allBusStop.put(temp.mID, temp);
                    }
                } catch (Exception e) {
                    break;
                }
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        // READ BUS ROUTE
        // TODO: fix
        try {
            downloaderBusRoute temp = new downloaderBusRoute(0, true);
            DataInputStream in = new DataInputStream(new FileInputStream(
                    allBusRouteBinary));
            char a;
            BusRoute route;

            while (true) {
                try {
                    route = new BusRoute();
                    route.BusRouteID = in.readShort();
                    // System.out.print(route.BusRouteID + "==");
                    while ((a = (char) in.readChar()) != 10) // \n charater
                    {
                        route.BusStopIDList.add(a);
                        // System.out.print(a + " ");
                    }
                    if (!allBusRoute.containsKey(route.BusRouteID)) {
                        allBusRoute.put(route.BusRouteID, route);
                    }
                } catch (Exception e) {
                    break;
                }
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    // produce train sequence with observation: CellID,
    // state: -1 if not near bus stop
    // BusStopID if within ReverseDistance metres previous or AcceptRadius
    // metres radius of the BusStop;
    // private LinkedList<Integer> mergeBusRoute (int busNumber)
    // {
    // LinkedList<Integer> tmp = new LinkedList<Integer> ();
    // if (allBusRoute.containsKey(busNumber)) {
    // tmp.addAll(allBusRoute.get(busNumber).BusStopIDList);
    // }
    // if (allBusRoute.containsKey(- busNumber)) {
    // tmp.addAll(allBusRoute.get(- busNumber).BusStopIDList);
    // }
    // return tmp;
    // }
    public LinkedList<Sequence> produceTrainSequence(
            LinkedList<Device> listOfDevices) {
        return produceTrainSequence(listOfDevices, 0);
    }

    // TODO: debug stuff, remove when cleaning code
    public void calculateDistanceOfBusStops() {
        Short sh;
        Set set = allBusRoute.keySet();
        Iterator it = set.iterator();
        BusRoute br = null;
        Character ch = null;
        double distance;
        BusStop bs1;
        BusStop bs2;
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(CONSTANTS.RESULT_FOLDER
                    + "distancebusstops.txt"), "UTF-8"));

            while (it.hasNext()) {
                sh = (Short) it.next();
                br = allBusRoute.get(sh);
                for (int i = 0; i < br.BusStopIDList.size(); i++) {
                    if (ch != null) {
                        bs1 = allBusStop.get(ch);
                        bs2 = allBusStop.get(br.BusStopIDList.get(i));
                        distance = CoordinateConversion.LatLngDistance(
                                bs1.mLat, bs1.mLng, bs2.mLat, bs2.mLng);
                        out.write(br.BusRouteID + "\t" + (int) bs1.mID + "\t"
                                + (int) bs2.mID + "\t" + distance + "\n");
                    }
                    ch = br.BusStopIDList.get(i);
                    if (br.BusRouteID == 37 && i == 14) {
                        ch = br.BusStopIDList.get(i);
                    }
                    ;
                }

                ch = null;
                System.out.println(br.BusRouteID);
            }
            System.out.println("FINAL" + br.BusRouteID);
            out.flush();
            out.close();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }

    public LinkedList<Sequence> produceTrainSequence(
            LinkedList<Device> listOfDevices, int indexOfCell) {
        LinkedList<Sequence> output = new LinkedList<Sequence>();
        Sequence seq;
        SequenceElement seqel;
        SequenceElement tmpSeqel;
        LinkedList<Character> br;
        BusStop bs;
        int tmp;
        Sample tmpS;
        double distance;
        char busStopID;
        int number;
        boolean fallIn = false;
        for (Device dev : listOfDevices) {
            System.out.println("Producing train sequence for file: "
                    + dev.filename);
            busStopID = (char) -1;
            if (allBusRoute.containsKey(dev.busNumber)) {
                seq = new Sequence();
                br = allBusRoute.get(dev.busNumber).BusStopIDList;
                seq.BusRouteID = dev.busNumber;
                for (Sample s : dev.sampleList) {
                    seqel = new SequenceElement();
                    if (indexOfCell < s.cellList.size()) {
                        seqel.Observation = (char) Integer.parseInt(s.cellList
                                .get(indexOfCell).id);
                        seqel.Lac = (char) Integer.parseInt(s.cellList
                                .get(indexOfCell).lac);
                    } else {
                        // Ex: get third cell when the cell list only have first
                        // and second cells
                        seqel.Observation = 0;
                        seqel.Lac = 0;
                    }

                    if (fallIn == false) {
                        double minDis = 1000;
                        BusStop minBS = null;
                        for (char j : br) {
                            bs = allBusStop.get(j);
                            distance = CoordinateConversion
                                    .LatLngDistance(Double.parseDouble(s.lat),
                                    Double.parseDouble(s.lng), bs.mLat,
                                    bs.mLng);
                            if (distance <= minDis) {
                                minBS = bs;
                                minDis = distance;
                            }
                        }
                        if (minDis <= AcceptRadius) {
                            busStopID = minBS.mID;
                            number = seq.size() - 1;
                            if (number != -1) {

                                while (number >= 1
                                        && seq.get(number).State == 0) {
                                    tmpSeqel = seq.get(number);
                                    tmpSeqel.State = busStopID;
                                    number--;
                                }
                                if (number == 0 && seq.get(0).State == 0) {
                                    seq.get(0).State = busStopID;
                                }
                            }
                            // break;
                        }

                    } else {
                        if (busStopID == 0 || busStopID == (char) -1) {
                            System.out.println("busStopID = " + busStopID
                                    + " FOR FILE: " + dev.filename);
                            continue;
                        }
                        bs = allBusStop.get(busStopID);
                        distance = CoordinateConversion.LatLngDistance(
                                Double.parseDouble(s.lat),
                                Double.parseDouble(s.lng), bs.mLat, bs.mLng);
                        // if (br.indexOf(busStopID) >= 27)
                        // System.out.println("FROM " + br.indexOf(busStopID) +
                        // "--" + distance);

                        if (distance <= AcceptRadius) {
                            // System.out.println("---------" +
                            // br.indexOf(busStopID)+ "--" + distance);
                            seqel.State = busStopID;
                        } else {
                            fallIn = false;
                        }
                    }
                    seq.add(seqel);
                }
                if (busStopID == (char) -1) {
                    System.out.println("none BusStop accepted FOR FILE: "
                            + dev.filename);
                    continue;
                }
                // seq.print(allBusRoute);
                // validate seq and preprocessed
                // smooth it out

                // write all the 0s to lastbusStopID;
                if (busStopID != br.getLast()) {
                    busStopID = br.get(br.indexOf(busStopID) + 1);
                }
                for (int i = seq.size() - 1; i >= 0; i--) {
                    if (seq.get(i).State == 0) {
                        seq.get(i).State = busStopID;
                    } else {
                        break;
                    }
                }

                boolean[] inOrderCheck = new boolean[100];
                int currentIndex = -1;
                boolean backtrack = false;
                boolean checkchange = false;
                for (int i = 0; i < seq.size(); i++) {
                    tmp = br.indexOf(seq.get(i).State);
                    if (currentIndex == -1) {
                        currentIndex = tmp;
                    } else {
                        if (tmp != currentIndex) {
                            if (inOrderCheck[currentIndex] == false) {
                                inOrderCheck[currentIndex] = true;
                            }
                            if (inOrderCheck[tmp] == false) {
                                for (int j = tmp + 1; j < 100; j++) {
                                    if (inOrderCheck[j] == true) {
                                        checkchange = true;
                                        inOrderCheck[j] = false;
                                    }
                                }
                                if (checkchange) {
                                    for (int j = 0; j <= i; j++) {
                                        if (seq.get(j).State != 0
                                                && inOrderCheck[br.indexOf(seq
                                                .get(j).State)] == false) {
                                            seq.get(j).State = 0;
                                            backtrack = true;
                                        }
                                    }
                                }
                                if (seq.get(i).State == 0) {
                                    currentIndex = -1;
                                } else {
                                    currentIndex = br.indexOf(seq.get(i).State);
                                }
                            } else {
                                seq.get(i).State = 0;
                                backtrack = true;
                            }
                        }
                    }
                }
                if (backtrack == true) {
                    tmp = seq.getLast().State;
                    for (int j = seq.size() - 1; j >= 0; j--) {
                        if (seq.get(j).State != 0) {
                            tmp = seq.get(j).State;
                            if (br.indexOf(tmp) != (br.size() - 1)) {
                                tmp = br.get(br.indexOf(tmp) + 1);
                            }
                            break;
                        }
                    }
                    for (int j = seq.size() - 1; j >= 0; j--) {
                        if (seq.get(j).State == 0) {
                            seq.get(j).State = (char) tmp;
                        } else {
                            tmp = seq.get(j).State;
                        }
                    }
                }
                // check first state
                boolean startAtFirst = false;
                bs = allBusStop.get(br.getFirst());
                tmp = br.indexOf(seq.getFirst().State);
                if (tmp == 0) {
                    startAtFirst = true;
                } else if (tmp == 1) {
                    int endtmp1 = 0;
                    while (br.indexOf(seq.get(endtmp1+1).State) == 1) {
                        endtmp1++;
                    }
                    boolean withinFirst = false;
                    for (int h = endtmp1; h >= 0; h--)
                    {
                        if (withinFirst == false)
                        {
                            tmpS = dev.sampleList.get(h);
                            distance = CoordinateConversion.LatLngDistance(
                                        Double.parseDouble(tmpS.lat),
                                        Double.parseDouble(tmpS.lng), bs.mLat,
                                        bs.mLng);
                            if (distance < AcceptRadiusForFirstAndLast)
                            {
                                seq.get(h).State = bs.mID;
                                withinFirst = true;
                                startAtFirst = true;
                            }  
                        }
                        else
                        {
                            seq.get(h).State = bs.mID;
                        }
                    }
                    
                    
                } 
                if (startAtFirst != true) {
                    System.out.println("File: " + dev.filename
                                + " start at BUSSTOPID index: " + tmp + " (NOT AT ZERO)");
                }
                // check last state
                tmp = br.indexOf(seq.getLast().State);
                if (tmp != (br.size() - 1)) {
                    System.out.println("File: " + dev.filename
                            + " end at BUSSTOPID index: " + tmp + " OF "
                            + (br.size() - 1) + " (NOT LAST)");
                }
                // check if increasing
                SequenceElement prev = null;

                for (SequenceElement sel : seq.sequenceinFile) {
                    if (prev == null) {
                        prev = sel;
                        continue;
                    } else if ((prev.State != sel.State)) {
                        if ((br.indexOf(prev.State) + 1) != br
                                .indexOf(sel.State)) {
                            System.out.println("SKIP BUSSTOP FROM "
                                    + (int) prev.State + "---"
                                    + br.indexOf(prev.State) + "---"
                                    + (int) prev.Observation);
                            System.out.println("SKIP BUSSTOP TO "
                                    + (int) sel.State + "---"
                                    + br.indexOf(sel.State) + "---"
                                    + (int) sel.Observation);
                        }
                    }
                    prev = sel;
                }
                System.out.println((int) seq.BusRouteID + " OF FILE: "
                        + dev.filename + " WITH " + br.size() + " BUSSTOPS");
                // seq.print(allBusRoute);
                output.add(seq);
            } else {
                System.err.println("DOESNT CONTAIN BUS NO: "
                        + (int) dev.busNumber + " OF FILE: " + dev.filename);
            }
        }

        // check sequence
        // try {
        // Writer out = new BufferedWriter(new OutputStreamWriter(
        // new FileOutputStream(CONSTANTS.RESULT_FOLDER
        // + "sequence.txt"), "UTF-8"));
        //
        // for (Sequence tseq : output) {
        // out.write(tseq.BusRouteID + "\n");
        // for (SequenceElement tsel : tseq.sequenceinFile) {
        // // if (tsel.Observation==49062)
        // out.write((int) tsel.State + ":" + (int) tsel.Observation
        // + "_" + (int) tsel.Lac + " ");
        // }
        // out.write("\n");
        // }
        // out.flush();
        // out.close();
        // } catch (Exception ex) {
        // ex.printStackTrace();
        // }
        //sampleBusStopDistance (listOfDevices, output);
        return output;
    }

    public BusStop getBusStop(char id) {
        if (allBusStop.containsKey(id)) {
            return allBusStop.get(id);
        } else {
            return null;
        }
    }

    public BusRoute getBusRoute(short id) {
        if (allBusRoute.containsKey(id)) {
            return allBusRoute.get(id);
        } else {
            return null;
        }
    }

    public double getDistanceBetweenBusStops(char id1, char id2) {
        BusStop bs1 = allBusStop.get(id1);
        BusStop bs2 = allBusStop.get(id2);
        if (bs1 == null || bs2 == null) {
            return 0;
        }
        return CoordinateConversion.LatLngDistance(bs1.mLat, bs1.mLng,
                bs2.mLat, bs2.mLng);
    }
    public double getDistanceBetweenBusStops(char id1, char id2, short busID)
    {
        Hashtable<Character, Hashtable <Character, Double>> sample = distanceBusStops.get(busID);
        Hashtable<Character, Double> sampleInner = null;
        if (sample != null) {
            if (sample.containsKey(id1)) {
                sampleInner = sample.get(id1);
                if (sampleInner.containsKey(id2)) {
//                    System.err.println(id1 + "  " + id2 + "   " + sampleInner.get(id2));
                    return sampleInner.get(id2);
                }
            }
        }
        return getDistanceBetweenBusStops(id1, id2);  
    }

    public double getDistanceFromStartToEnd(short busroute, char id1, char id2) {
        BusRoute br = allBusRoute.get(busroute);
        if (br == null || !br.BusStopIDList.contains(id1) || !br.BusStopIDList.contains(id2)) {
            return 0;
        }

        double distance = 0;

        int start = 0, end = 0;
        for (int i = 0; i < br.BusStopIDList.size(); i++) {
            start = i;
            if (br.BusStopIDList.get(i).compareTo(id1) == 0) {
                break;
            }
        }

        for (int i = 0; i < br.BusStopIDList.size(); i++) {
            end = i;
            if (br.BusStopIDList.get(i).compareTo(id2) == 0) {
                break;
            }
        }


        for (; start < end; start++) {
            distance += getDistanceBetweenBusStops(br.BusStopIDList.get(start), br.BusStopIDList.get(start + 1));
        }
        System.out.println("getDistanceFromStartToEnd " + busroute + " " + (int) id1 + " " + (int) id2);
        System.out.println("getDistanceFromStartToEnd " + distance);

        return distance;
    }

    boolean isUrban(char State) {
        BusStop bs = allBusStop.get(State);
        if (!(bs.mDistrict.contains("12")) && (bs.mDistrict.contains("1")||bs.mDistrict.contains("3")||bs.mDistrict.contains("4")
                ||bs.mDistrict.contains("5")||bs.mDistrict.contains("6")||bs.mDistrict.contains("8")))
            return true;
        else
            return false;
    }

    private void sampleBusStopDistance(LinkedList<Device> listOfDevices, LinkedList<Sequence> output) {
        Hashtable<Character, Hashtable <Character, Double>> sample = null;
        Hashtable<Character, Double> sampleInner = null;
        Device currentd = null;
        Sequence currentseq = null;
        char prevState = 0;
        char currState = 0;
        double prevLng = 0;
        double prevLat = 0;
        double distance = 0;
        char fromState = 0;
        for (int i = 0; i < output.size(); i++)
        {
            sample = new Hashtable<Character, Hashtable<Character, Double>>();
            currentd = listOfDevices.get(i);
            currentseq = output.get(i);
            sampleInner = null;
            currState = 0;
            prevLng = Double.parseDouble(currentd.sampleList.getFirst().lng);
            prevLat = Double.parseDouble(currentd.sampleList.getFirst().lat);
            distance = 0;
            prevState = currentseq.getFirst().State;
            fromState = 0;
            for (int j = 1; j < currentseq.size(); j++)
            {
                currState = currentseq.get(j).State;
                distance += CoordinateConversion.LatLngDistance(prevLat, prevLng, 
                            Double.parseDouble(currentd.sampleList.get(j).lat), 
                            Double.parseDouble(currentd.sampleList.get(j).lng));
                if (currState == prevState)
                {
                }
                else {
                    if (fromState == 0) {
                        
                    } else {
                        if (Math.abs(getDistanceBetweenBusStops(fromState, prevState) - distance) >= DistanceDiffToSave) {
                            distance = (getDistanceBetweenBusStops(fromState, currState) + distance) / 2;
                            if (sample.containsKey(fromState))
                            {
                                sampleInner = sample.get(fromState);
                                if (sampleInner.containsKey(prevState))
                                {
                                    System.err.println("STRANGE: ALREADY IN SAMPLEINNER");
                                }
                                else
                                {
                                    sampleInner.put(prevState, distance);
                                    sample.put(fromState, sampleInner);
                                }
                            } else {
                                sampleInner = new Hashtable<Character, Double>();
                                sampleInner.put(prevState, distance);
                                sample.put(fromState, sampleInner);
                            }
                        }
                    }
                    fromState = prevState;
                    distance = 0;
                }
                
                prevLng = Double.parseDouble(currentd.sampleList.get(j).lng);
                prevLat = Double.parseDouble(currentd.sampleList.get(j).lat);
                prevState = currState;
            }
            if (Math.abs(getDistanceBetweenBusStops(fromState, currState) - distance) >= DistanceDiffToSave) {
                System.err.println("BUSID: " + currentd.busNumber + " from " + (int)fromState + " to " + (int)currState);
                System.err.println("Calculated : " + distance + " straightline: " + getDistanceBetweenBusStops(fromState, currState) +  " => Diff : " + (Math.abs(getDistanceBetweenBusStops(fromState, currState) - distance)));
                distance = (getDistanceBetweenBusStops(fromState, currState) + distance) / 2;
                if (sample.containsKey(fromState))
                    {
                        sampleInner = sample.get(fromState);
                        if (sampleInner.containsKey(currState)) {
                            System.err.println("STRANGE: ALREADY IN SAMPLEINNER");
                        } else {
                            sampleInner.put(currState, distance);
                            sample.put(fromState, sampleInner);
                        }
                    } else {
                        sampleInner = new Hashtable<Character, Double>();
                        sampleInner.put(currState, distance);
                        sample.put(fromState, sampleInner);
                 }
            }
            if (sample.size() != 0)
                distanceBusStops.put(currentd.busNumber, sample);
        }
    }
}
